package JDK常用类库.stream;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author：russ
 * @Date：2023/8/12
 * @apiNote：
 */
public class StreamTest1 {

    /**
     * 使用 map() 方法将每个字符串转换为大写
     */
    @Test
    public void test1(){
        List<String> words = Arrays.asList("hello", "world", "java", "stream");
        List<String> capitalizedWords = words.stream()
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        System.out.println("Capitalized words: " + capitalizedWords);
    }

    /**
     * 使用 flatMap() 方法将嵌套的列表展平为一个列表
     */
    @Test
    public void test2(){
        List<List<Integer>> nestedNumbers = Arrays.asList(
                Arrays.asList(1, 2),
                Arrays.asList(3, 4, 5),
                Arrays.asList(6, 7, 8, 9)
        );

        List<Integer> flattenedNumbers = nestedNumbers.stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());

        System.out.println("Flattened numbers: " + flattenedNumbers);
    }


    /**
     * 使用 peek() 方法打印每个元素并统计元素个数
     */
    @Test
    public void test3(){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        int count = numbers.stream()
                .peek(System.out::println)
                .mapToInt(Integer::intValue)
                .sum();

        System.out.println("Total count: " + count);
    }


    /**
     * 使用 toArray() 方法将 Stream 转换为数组
     */
    @Test
    public void test4(){
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer[] numberArray = numbers.stream()
                .toArray(Integer[]::new);
        System.out.println("Number array: " + Arrays.toString(numberArray));
    }
    /**
     * 使用 anyMatch() 判断列表中是否存在以字母"a"开头的字符串
     */
    @Test
    public void test5(){
        String[] strings = {"apple", "banana", "cherry", "date"};
        boolean result = Arrays.stream(strings).anyMatch(s -> s.startsWith("a"));
        System.out.println("Result: " + result);
    }

    /**
     * 使用 allMatch() 判断列表中的所有字符串是否都以字母"a"开头
     */
    @Test
    public void test6(){
        String[] strings = {"apple", "avocado", "apricot", "almond"};
        boolean result = Arrays.stream(strings).allMatch(s -> s.startsWith("a"));
        System.out.println("Result: " + result);
    }

    /**
     * 使用 noneMatch() 判断列表中是否不存在包含字母"z"的字符串
     */
    @Test
    public void test7(){
        String[] strings = {"apple", "banana", "cherry", "date"};
        boolean result = Arrays.stream(strings).noneMatch(s -> s.contains("z"));
        System.out.println("Result: " + result);
    }

    /**
     * 使用 findFirst() 从列表中找到第一个长度为 4 的字符串
     */
    @Test
    public void test8(){
        String[] strings = {"apple", "banana", "cherry", "date"};
        Optional<String> result = Arrays.stream(strings).filter(s -> s.length() == 4).findFirst();
        System.out.println("Result: " + result.orElse("Not found"));
    }
    /**
     * 使用 flatMapping() 将嵌套的字符串列表展平为一个字符串列表
     */
    @Test
    public void test9(){
        List<List<String>> nestedList = Arrays.asList(
                Arrays.asList("hello", "world"),
                Arrays.asList("hello","java", "stream"));
        List<String> result = nestedList.stream()
                .flatMap(List::stream)
                .distinct()
                .collect(Collectors.toList());
        System.out.println(result);
    }

    /**
     * 使用 iterating() 生成斐波那契数列前 10 项
     */
    @Test
    public void test10(){
        Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]})
                .limit(10)
                .map(t -> t[0])
                .forEach(System.out::println);
    }

    /**
     * 使用 empty() 使用空的 Stream
     */
    @Test
    public void test11(){
        Stream<String> emptyStream = Stream.empty();
        System.out.println(emptyStream.count());
    }


    /**
     * 使用 unordered() 对数字列表进行排序后，使用 unordered()返回一个无序的 Stream
     * 这个方法有个小坑：https://juejin.cn/post/7221345151113904186
     */
    @Test
    public void test12(){
        List<Integer> numberList = Arrays.asList(1, 3, 2, 4, 10, 6, 8, 7, 9, 6);
        List<Integer> result = numberList.stream()
                .sorted()
                .unordered()
                .collect(Collectors.toList());
        System.out.println(result);
    }

    /**
     * 集合迭代 vs 使用Stream API进行过滤和映射
     */
    @Test
    public void test13(){
        /**
         * 列表中的偶数
         */
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        for (int i : list) {
            if (i % 2 == 0) {
                System.out.println(i);
            }
        }

        System.out.println();
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        numbers.stream()
                .filter(number -> number % 2 == 0)
                .forEach(System.out::println);
    }

    /**
     * 计算列表中偶数的平方和
     */
    @Test
    public void test14(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        int sum = 0;
        for (int number : list) {
            if (number % 2 == 0) {
                int square = number * number;
                sum += square;
            }
        }
        System.out.println(sum);

        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        int res = numbers.stream()
                .filter(number -> number % 2 == 0)
                .mapToInt(number -> number * number)
                .sum();
        System.out.println(res);
    }

    /**
     * 过滤出长度大于5的水果，并将结果转换为大写
     */
    @Test
    public void test15(){
        List<String> list = Arrays.asList("apple", "banana", "cherry", "date");
        List<String> res = new ArrayList<>();
        for(String i : list){
            if(i.length() > 5){
                res.add(i.toUpperCase());
            }
        }
        System.out.println(res);
        List<String> fruits = Arrays.asList("apple", "banana", "cherry", "date");
        List<String> filteredAndMapped = fruits.stream()
                .filter(fruit -> fruit.length() > 5)
                .map(String::toUpperCase)
                .collect(Collectors.toList());

        System.out.println(filteredAndMapped);
    }
}
